package com.project.nimsen.util;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
/**
 * 生成二维码的工具类
 * */
public class ZxingUtil {
	/**
	 * 生成普通二维码
	 * 
	 * @param contents
	 * @param width 像素值
	 * @param height 像素值
	 * @param output 输出流
	 */
	public static void encodePR(String contents, int width, int height, OutputStream output)throws Exception {
		Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
		// 指定纠错等级
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
		// 指定编码格式
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		hints.put(EncodeHintType.MARGIN, 1);
		BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
				BarcodeFormat.QR_CODE, width, height, hints);
		MatrixToImageWriter.writeToStream(bitMatrix, "jpg", output, new MatrixToImageConfig(0xFF000000,0xFFFFFFFF));
	}
	/**
	 * 产生带有图片的二维码缓冲图像
	 * @param content
	 * @param width
	 * @param height
	 * @param output 输出流
	 * @return
	 * @throws WriterException
	 * @throws IOException
	 */
	private static BufferedImage genBarcode(String content, int width, int height,
			File inFile) throws WriterException, IOException {
		int login_width = width/40*9;
		int login_height = height/40*9;
		int login_half_width = login_width/2;
		int login_frame_width=width/80;
		// 读取源图像
		BufferedImage scaleImage = scale(inFile, login_width, login_height, true, false);
		int[][] srcPixels = new int[login_width][login_height];
		for (int i = 0; i < scaleImage.getWidth(); i++) {
			for (int j = 0; j < scaleImage.getHeight(); j++) {
				srcPixels[i][j] = scaleImage.getRGB(i, j);
			}
		}

		Map<EncodeHintType, Object> hint = new HashMap<EncodeHintType, Object>();
		hint.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		hint.put(EncodeHintType.MARGIN, 1);
		// 生成二维码
		MultiFormatWriter mutiWriter = new MultiFormatWriter();
		BitMatrix matrix = mutiWriter.encode(content, BarcodeFormat.QR_CODE,
				width, height, hint);

		// 二维矩阵转为一维像素数组
		int halfW = matrix.getWidth() / 2;
		int halfH = matrix.getHeight() / 2;
		int[] pixels = new int[width * height];

		for (int y = 0; y < matrix.getHeight(); y++) {
			for (int x = 0; x < matrix.getWidth(); x++) {
				// 读取图片
				if (x > halfW - login_half_width
						&& x < halfW + login_half_width
						&& y > halfH - login_half_width
						&& y < halfH + login_half_width) {
					pixels[y * width + x] = srcPixels[x - halfW
							+ login_half_width][y - halfH + login_half_width];
				}
				// 在图片四周形成边框
				else if ((x > halfW - login_half_width - login_frame_width
						&& x < halfW - login_half_width + login_frame_width
						&& y > halfH - login_half_width - login_frame_width && y < halfH
						+ login_half_width + login_frame_width)
						|| (x > halfW + login_half_width - login_frame_width
								&& x < halfW + login_half_width + login_frame_width
								&& y > halfH - login_half_width - login_frame_width && y < halfH
								+ login_half_width + login_frame_width)
						|| (x > halfW - login_half_width - login_frame_width
								&& x < halfW + login_half_width + login_frame_width
								&& y > halfH - login_half_width - login_frame_width && y < halfH
								- login_half_width + login_frame_width)
						|| (x > halfW - login_half_width - login_frame_width
								&& x < halfW + login_half_width + login_frame_width
								&& y > halfH + login_half_width - login_frame_width && y < halfH
								+ login_half_width + login_frame_width)) {
					pixels[y * width + x] = 0xfffffff;
				} else {
					// 此处可以修改二维码的颜色，可以分别制定二维码和背景的颜色；
					pixels[y * width + x] = matrix.get(x, y) ? 0xff000000
							: 0xfffffff;
				}
			}
		}

		BufferedImage image = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		image.getRaster().setDataElements(0, 0, width, height, pixels);

		return image;
	}
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * 生成带图片的二维码
	 * 
	 * @param content
	 * @param width 像素值
	 * @param height 像素值
	 * @param output 输出流
	 * @param inFile 头像的图片
	 */
	public static void encodePR(String content, int width, int height,
			OutputStream output, File inFile)throws Exception {
			ImageIO.write(genBarcode(content, width, height, inFile),
				"jpg", output);
			inFile.delete();
	}

	/**
	 * 针对二维码进行解析
	 * 
	 * @param imgPath
	 * @return
	 * @throws Exception 
	 */
	public static String decodePR(File imgPath) throws Exception {
		BufferedImage image = null;
		Result result = null;
		image = ImageIO.read(imgPath);
		if (image == null) {
			throw new IOException("the decode image may be not exists.");
		}
		LuminanceSource source = new BufferedImageLuminanceSource(image);
		BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

		Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
		hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");

		result = new MultiFormatReader().decode(bitmap, hints);
		return result.getText();
	}

	/**
	 * 创建条形码
	 * 
	 * @param contents
	 * @param width 像素值
	 * @param height 像素值
	 * @param output 输出流
	 */
	public static void encodeBar(String contents, int width, int height, OutputStream output)throws Exception {
		// 条形码的最小宽度
		int codeWidth = 98;
		codeWidth = Math.max(codeWidth, width);
		BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
				BarcodeFormat.EAN_13, codeWidth, height, null);
		MatrixToImageWriter.writeToStream(bitMatrix, "png", output);
	}

	/**
	 * 针对条形码进行解析
	 * 
	 * @param outFile  二维码输出的文件
	 * @return
	 */
	public static String decodeBar(File outFile) throws Exception {
		BufferedImage image = ImageIO.read(outFile);
		if (image == null) {
			throw new IOException("the decode image may be not exists.");
		}
		LuminanceSource source = new BufferedImageLuminanceSource(image);
		BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

		Result result = new MultiFormatReader().decode(bitmap, null);
		return result.getText();
	}

	/**
	 * 把传入的原始图像按高度和宽度进行缩放，生成符合要求的图标
	 * 
	 * @param infile 读取的图像
	 * @param height 目标高度
	 * @param width 目标宽度
	 * @param hasFiller 比例不对时是否需要补白：true为补白; false为不补白;
	 * @param hasscale 对于login是否进行缩放
	 * @throws IOException
	 */
	private static BufferedImage scale(File infile, int height, int width,
			boolean hasFiller, boolean hasscale) throws IOException {
		double ratio = 0.0; // 缩放比例
		BufferedImage srcImage = ImageIO.read(infile);
		Image destImage = srcImage.getScaledInstance(width, height,
				BufferedImage.SCALE_SMOOTH);
		// 计算比例
		if(hasscale)
			if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
				if (srcImage.getHeight() > srcImage.getWidth()) {
					ratio = (new Integer(height)).doubleValue()
							/ srcImage.getHeight();
				} else {
					ratio = (new Integer(width)).doubleValue()
							/ srcImage.getWidth();
				}
				AffineTransformOp op = new AffineTransformOp(
						AffineTransform.getScaleInstance(ratio, ratio), null);
				destImage = op.filter(srcImage, null);
			}
		if (hasFiller) {// 补白
			BufferedImage image = new BufferedImage(width, height,
					BufferedImage.TYPE_INT_RGB);
			Graphics2D graphic = image.createGraphics();
			graphic.setColor(Color.white);
			graphic.fillRect(0, 0, width, height);
			if (width == destImage.getWidth(null))
				graphic.drawImage(destImage, 0,
						(height - destImage.getHeight(null)) / 2,
						destImage.getWidth(null), destImage.getHeight(null),
						Color.white, null);
			else
				graphic.drawImage(destImage,
						(width - destImage.getWidth(null)) / 2, 0,
						destImage.getWidth(null), destImage.getHeight(null),
						Color.white, null);
			graphic.dispose();
			destImage = image;
		}
		return (BufferedImage) destImage;
	}
//	public static void main(String[] args) throws Exception {
//		File imgPath = new File("d:/pr1.jpg");
//		
//		String contents = "BEGIN:VCARD \nVERSION:3.0 \nN:杜说 \nEMAIL:accpdubing@gmail.com \nTEL:18103896062 \nTEL;CELL:18103896063 \nTEL:126 \nADR;WORK:河南省济源市 \nORG:济源微盟 \nTITLE:技术员 \nURL:http://www.f273c.com \nNOTE:多断镜子芳 \nEND:VCARD";
//		// 普通二维码的生成与解析
//		ZXxingUtil.encodePR(contents, 300, 300, new FileOutputStream(imgPath));
//		System.out.println("生成二维码成功");
//		System.out.println(ZXxingUtil.decodePR(imgPath));
//
//		 //带图片的二维的生成与解析
//		File srcPath = new File("d:/1375416177888.jpg");
//		ZXxingUtil.encodePR(contents, 900, 900, new FileOutputStream(imgPath),srcPath);
//		System.out.println("生成带图片的二维码成功");
//		System.out.println(ZXxingUtil.decodePR(imgPath));
//
//		// 条形码的生成与解析
//		ZXxingUtil.encodeBar("6923450657713", 105, 50, new FileOutputStream(imgPath));
//		System.out.println("生成条形码成功");
//		System.out.println(ZXxingUtil.decodeBar(imgPath));
//	}
}
